package com.sun.controller;


import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.sun.common.Limit;
import com.sun.common.QueryPageParam;
import com.sun.common.Result;
import com.sun.entity.Menu;
import com.sun.entity.User;
import com.sun.service.MenuService;
import com.sun.service.UserService;
import com.sun.until.MD5;
import com.sun.until.MyRandomUntil;
import com.sun.until.PhoneNumberUntil;
import com.sun.until.UserUntil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpSession;
import java.util.HashMap;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;

/**
 * <p>
 * 前端控制器：用户管理和管理员管理模块
 * </p>
 *
 * @author rabbiter
 * @since 2023-01-02
 */
@RestController
@RequestMapping("/user")
public class UserController {
    @Autowired
    private UserService userService;
    @Autowired
    private MenuService menuService;
    @Autowired
    private RedisTemplate<String, Object> redisTemplate;

    private ConcurrentHashMap<String, String> localCache = new ConcurrentHashMap<>();


    /*
     * 查询全部用户
     * @author rabbiter
     * @date 2023/1/2 19:26
     */
    @GetMapping("/list")
    public List<User> list() {
        return userService.list();
    }

    /*
     * 根据账号查找用户
     * @author rabbiter
     * @date 2023/1/4 14:53
     */
    @GetMapping("/findByNo")
    public Result findByNo(@RequestParam String no) {
        List list = userService.lambdaQuery()
                .eq(User::getNo, no)
                .list();
        return list.size() > 0 ? Result.success(list) : Result.fail();
    }

    /*
     * 新增用户
     * @author rabbiter
     * @date 2023/1/2 19:11
     */
    @PostMapping("/save")
    public Result save(@RequestBody User user) {
        String encode = MD5.encode(user.getPassword());
        user.setPassword(encode);
        return userService.save(user) ? Result.success() : Result.fail();
    }

    /*
     * 更新用户
     * @author rabbiter
     * @date 2023/1/2 19:11
     */
    @PostMapping("/update")
    public Result update(@RequestBody User user) {
        return userService.updateById(user) ? Result.success() : Result.fail();
    }

    /*
     * 用户登录：登录的时候一并将菜单信息也查询出来
     * @author rabbiter
     * @date 2023/1/3 14:08
     */
//    @PostMapping("/login")
//    public Result login(@RequestBody User user){
//        String Key = "login:" + user.getNo();
//
//
//
//        if (Boolean.TRUE.equals(redisTemplate.hasKey(Key))){
//            String json = (String) redisTemplate.opsForValue().get(Key);
//            User user1 = JSONUtil.toBean(json, User.class);
//            List<Menu> menuList = menuService.lambdaQuery()
//                    .like(Menu::getMenuright,user1.getRoleId())
//                    .list();
//            HashMap res = new HashMap();
//            res.put("user",user1);
//            res.put("menu",menuList);
//            return Result.success(res);
//        }else {
//            //匹配账号和密码
//            List list = userService.lambdaQuery()
//                    .eq(User::getNo,user.getNo())
//                    .eq(User::getPassword, MD5.encode(user.getPassword()))
//                    .list();
//            if(list.size()>0){
//                User user1 = (User)list.get(0);
//                List<Menu> menuList = menuService.lambdaQuery()
//                        .like(Menu::getMenuright,user1.getRoleId())
//                        .list();
//                HashMap res = new HashMap();
//                res.put("user",user1);
//                res.put("menu",menuList);
//                return Result.success(res);
//                String jsonStr = JSONUtil.toJsonStr(user1);
//                redisTemplate.opsForValue().set(Key, jsonStr, 1, TimeUnit.HOURS);
//            }
//
//
//            return Result.fail();
//        }
//
//    }

    //
//    @PostMapping("/login")
//    public Result login(@RequestBody User user){
//        String Key = "login:" + user.getNo();
//
//        if (Boolean.TRUE.equals(redisTemplate.hasKey(Key))){
//            String json = (String) redisTemplate.opsForValue().get(Key);
//            User user1 = JSONUtil.toBean(json, User.class);
//            List<Menu> menuList = menuService.lambdaQuery()
//                    .like(Menu::getMenuright,user1.getRoleId())
//                    .list();
//            HashMap res = new HashMap();
//            res.put("user",user1);
//            res.put("menu",menuList);
//            return Result.success(res);
//        }else {
//            //匹配账号和密码
//            List list = userService.lambdaQuery()
//                    .eq(User::getNo,user.getNo())
//                    .eq(User::getPassword, MD5.encode(user.getPassword()))
//                    .list();
//            if(list.size()>0){
//                User user1 = (User)list.get(0);
//                String jsonStr = JSONUtil.toJsonStr(user1);
//                redisTemplate.opsForValue().set(Key, jsonStr, 1, TimeUnit.HOURS);
//                List<Menu> menuList = menuService.lambdaQuery()
//                        .like(Menu::getMenuright,user1.getRoleId())
//                        .list();
//                HashMap res = new HashMap();
//                res.put("user",user1);
//                res.put("menu",menuList);
//                return Result.success(res);
//            }
//            return Result.fail();
//        }
//    }
    @Limit(key = "limitTest", period = 100, count = 3)
    @PostMapping("/login")
    public Result login(@RequestBody User user, HttpSession session) {
        String Key = "login:" + user.getNo();
        if (localCache.containsKey(Key)) {
            String json = localCache.get(Key);
            User user1 = JSONUtil.toBean(json, User.class);
            List<Menu> menuList = menuService.lambdaQuery()
                    .like(Menu::getMenuright, user1.getRoleId())
                    .list();
            HashMap res = new HashMap();
            res.put("user", user1);
            res.put("menu", menuList);
            UserUntil.setUserBySession(session, user1);
            return Result.success(res);
        } else if (Boolean.TRUE.equals(redisTemplate.hasKey(Key))) {
            String json = (String) redisTemplate.opsForValue().get(Key);
            User user1 = JSONUtil.toBean(json, User.class);
            List<Menu> menuList = menuService.lambdaQuery()
                    .like(Menu::getMenuright, user1.getRoleId())
                    .list();
            HashMap res = new HashMap();
            res.put("user", user1);
            res.put("menu", menuList);
            localCache.put(Key, json);  // 将数据添加到本地缓存
            UserUntil.setUserBySession(session, user1);
            return Result.success(res);
        } else {
            //匹配账号和密码
            List list = userService.lambdaQuery()
                    .eq(User::getNo, user.getNo())
                    .eq(User::getPassword, MD5.encode(user.getPassword()))
                    .list();
            if (list.size() > 0) {
                User user1 = (User) list.get(0);
                String jsonStr = JSONUtil.toJsonStr(user1);
                redisTemplate.opsForValue().set(Key, jsonStr, 1, TimeUnit.HOURS);
                redisTemplate.opsForValue().set("user", jsonStr);
                redisTemplate.expire("user",1,TimeUnit.DAYS);
                localCache.put(Key, jsonStr);
                List<Menu> menuList = menuService.lambdaQuery()
                        .like(Menu::getMenuright, user1.getRoleId())
                        .list();
                HashMap res = new HashMap();
                res.put("user", user1);
                res.put("menu", menuList);
                UserUntil.setUserBySession(session, user1);
                return Result.success(res);
            }
            return Result.fail();
        }
    }


    @PostMapping("/sendSmsCode")
    public Result sendSmsCode(@RequestBody HashMap<String, Object> map) {
        String phone = (String) map.get("phone");
        if (phone == null || phone.isEmpty() || !PhoneNumberUntil.isValidChinesePhoneNumber(phone)) {
            return Result.fail(400, "手机号码为空或手机号不正确");
        }
        String hourNumKey = "smsCode:hour:" + phone;
        Integer hourNumValue = (Integer) redisTemplate.opsForValue().get(hourNumKey);
        if (hourNumValue != null && hourNumValue > 5) {
            return Result.fail(400, "一小时内验证码发送次数过多");
        }
        Boolean hourHashkey = redisTemplate.hasKey(hourNumKey);
        if (!hourHashkey) {
            redisTemplate.opsForValue().set(hourNumKey, 1, 1, TimeUnit.DAYS);
        } else {
            redisTemplate.opsForValue().increment(hourNumKey, 1);
        }
        String dayNumKey = "smsCode:day:" + phone;
        Integer dayNumValue = (Integer) redisTemplate.opsForValue().get(dayNumKey);
        if (dayNumValue != null && dayNumValue > 20) {
            return Result.fail(400, "今天验证码发送次数过多");
        }
        Boolean dayHashkey = redisTemplate.hasKey(hourNumKey);
        if (!dayHashkey) {
            redisTemplate.opsForValue().set(hourNumKey, 1, 1, TimeUnit.DAYS);
        } else {
            redisTemplate.opsForValue().increment(dayNumKey, 1);
        }
        String key = "smsCode:" + phone;
        Boolean hashkey = redisTemplate.hasKey(key);
        if (hashkey) {
            return Result.fail(400, "已发送过验证码");
        } else {
            redisTemplate.opsForValue().set(key, MyRandomUntil.randomCode(1), 5, TimeUnit.MINUTES);
        }
        try {
            return Result.success();
        } catch (Exception e) {
            return Result.fail(400, "短信发送失败！");
        }
    }

    @PostMapping("/login/sms")
    public Result sms(@RequestBody HashMap<String, Object> map, HttpSession session) {

        String phone = (String) map.get("phone");
        String sms_code = (String) map.get("sms_code");

        if (sms_code == null || sms_code.length() < 6) {
            return Result.fail(400, "验证码错误");
        }

        String key = "smsCode:" + phone;
        try {
            String code = (String) redisTemplate.opsForValue().get(key);
            if (sms_code.equals(code)) {

                //匹配账号和密码
                List list = userService.lambdaQuery()
                        .eq(User::getPhone, phone)
                        .list();

                if (list.size() > 0) {
                    User user1 = (User) list.get(0);
                    List<Menu> menuList = menuService.lambdaQuery()
                            .like(Menu::getMenuright, user1.getRoleId())
                            .list();
                    HashMap res = new HashMap();
                    res.put("user", user1);
                    res.put("menu", menuList);


                    //
                    String jsonStr = JSONUtil.toJsonStr(user1);
                    redisTemplate.opsForValue().set("user", jsonStr);
                    redisTemplate.expire("user",1,TimeUnit.DAYS);

                    return Result.success(res);
                }
                return Result.fail(400, "密码错误！");
            } else {
                return Result.fail(400, "验证码错误！");
            }
        } catch (Exception e) {
            return Result.fail();
        }
    }


    /*
     * 修改用户
     * @author rabbiter
     * @date 2023/1/4 15:02
     */
    @PostMapping("/mod")
    public boolean mod(@RequestBody User user) {
        return userService.updateById(user);
    }

    /*
     * 新增或修改：存在用户则修改，否则新增用户
     * @author rabbiter
     * @date 2023/1/2 19:12
     */
    @PostMapping("/saveOrUpdate")
    public Result saveOrUpdate(@RequestBody User user) {
        String encode = MD5.encode(user.getPassword());
        user.setPassword(encode);
        return userService.saveOrUpdate(user) ? Result.success() : Result.fail();
    }

    /*
     * 删除用户
     * @author rabbiter
     * @date 2023/1/2 19:15
     */
    @GetMapping("/del")
    public Result delete(Integer id) {
        return userService.removeById(id) ? Result.success() : Result.fail();
    }

    /*
     * 模糊查询
     * @author rabbiter
     * @date 2023/1/2 19:36
     */
    @PostMapping("/listP")
    public Result query(@RequestBody User user) {


        LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
        if (StringUtils.isNotBlank(user.getName())) {
            wrapper.like(User::getName, user.getName());
        }
        return Result.success(userService.list(wrapper));
    }

    /*
     * 分页查询
     * @author rabbiter
     * @date 2023/1/2 19:48
     */
//    @PostMapping("/listPage")
//    public Result page(@RequestBody QueryPageParam query){
//        HashMap param = query.getParam();
//        String name = (String)param.get("name");
//
//        Page<User> page = new Page();
//        page.setCurrent(query.getPageNum());
//        page.setSize(query.getPageSize());
//
//        LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
//        wrapper.like(User::getName,name);
//
//        IPage result = userService.page(page,wrapper);
//        return Result.success(result.getRecords(),result.getTotal());
//    }

    @PostMapping("/listPage")
    public List<User> listPage(@RequestBody QueryPageParam query, HttpSession session) {

        User userBySession = UserUntil.getUserBySession(session);


        HashMap param = query.getParam();
        String name = (String) param.get("name");
        System.out.println("name=>" + (String) param.get("name"));

        Page<User> page = new Page();
        page.setCurrent(query.getPageNum());
        page.setSize(query.getPageSize());

        LambdaQueryWrapper<User> lambdaQueryWrapper = new LambdaQueryWrapper();
        lambdaQueryWrapper.like(User::getName, name);


        IPage result = userService.page(page, lambdaQueryWrapper);

        System.out.println("total=>" + result.getTotal());

        return result.getRecords();
    }

    /*
     * 查询功能：根据前端表单输入的信息或者下拉框选择查询用户，并以分页的形式返回前端
     * @author rabbiter
     * @date 2023/1/4 20:28
     */
    @PostMapping("/listPageC1")
    public Result listPageC1(@RequestBody QueryPageParam query) {
        HashMap param = query.getParam();
        String name = (String) param.get("name");
        String sex = (String) param.get("sex");
        String roleId = (String) param.get("roleId");

        Page<User> page = new Page();
        page.setCurrent(query.getPageNum());
        page.setSize(query.getPageSize());

        LambdaQueryWrapper<User> lambdaQueryWrapper = new LambdaQueryWrapper();
        if (StringUtils.isNotBlank(name) && !"null".equals(name)) {
            lambdaQueryWrapper.like(User::getName, name);
        }
        if (StringUtils.isNotBlank(sex)) {
            lambdaQueryWrapper.eq(User::getSex, sex);
        }
        if (StringUtils.isNotBlank(roleId)) {
            lambdaQueryWrapper.eq(User::getRoleId, roleId);
        }

        IPage result = userService.pageCC(page, lambdaQueryWrapper);

        System.out.println("total=>" + result.getTotal());


        return Result.success(result.getRecords(), result.getTotal());
    }


    @GetMapping("/logout")
    public Result logout() {

        String json = (String) redisTemplate.opsForValue().get("user");
        User user1 = JSONUtil.toBean(json, User.class);

        redisTemplate.delete("user");
        redisTemplate.delete("login:" + user1.getNo());
        localCache.clear();

        return Result.success();
    }


    @GetMapping("/Admin")
    public Result admin() {
        List<String> strings = userService.seletAdmin();
        return Result.success(strings);
    }


}
